#include "utils.h"
#include "global_var.h"
#include "data_bean.h"

#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QDebug>
#include <QFile>
#include <QByteArray>
#include <QDir>

User err_user;
Group err_group;
Task err_task;

bool is_user_id_exist(const QString& str) {
    for(int i = 0; i < users.length(); i++) {
        if(str == users.at(i).getId()) {
            return true;
        }
    }
    return false;
}

void load_json() {
    load_users();
    load_groups();
    load_tasks();
}

void load_users()
{
    QFile file(":/store/users.json");
    file.open(QIODevice::Text | QIODevice::ReadOnly);
    QString value = file.readAll();
    file.close();

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(value.toUtf8(), &error);

    if (!(error.error == QJsonParseError::NoError)) {
        qDebug() << "No users.json" << endl;
        return;
    }

    QJsonArray user_array = doc.array();

    for(int i=0; i < user_array.size(); i++) {
        if(user_array[i].isObject()) {
            QJsonObject obj = user_array[i].toObject();

            USER_ROLE role;
            if(obj["role"] == "manager") {
                role = MANAGER;
            }
            else if(obj["role"] == "teacher") {
                role = TEACHER;
            }
            else {
                role = STUDENT;
            }

            User new_user(obj["id"].toString(), obj["password"].toString(), role,
                    obj["email"].toString(), obj["phone"].toString());

            users.push_back(new_user);
        }
    }
}

void load_groups() {
    QFile file(":/store/groups.json");

    file.open(QIODevice::Text | QIODevice::ReadOnly);
    QString value = file.readAll();
    file.close();

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(value.toUtf8(), &error);

    if (!(error.error == QJsonParseError::NoError)) {
        qDebug() << "No groups.json" << endl;
        return;
    }

    QJsonArray group_array = doc.array();

    for(int i=0; i < group_array.size(); i++) {
        if(group_array[i].isObject()) {
            QJsonObject obj = group_array[i].toObject();

            Group new_group(obj["gid"].toString(), obj["gname"].toString(), obj["manager"].toString());

            if(obj["members"].isArray()) {
                QJsonArray member_array = obj["members"].toArray();
                for(int k=0; k < member_array.size(); k++) {
                    new_group.add_user(member_array[i].toString());
                }
            }

            groups.push_back(new_group);
        }
    }
}

void load_tasks() {
    QFile file(":/store/tasks.json");
    const QString datetime_format = "yyyy-MM-dd hh:mm:ss";

    file.open(QIODevice::Text | QIODevice::ReadOnly);
    QString value = file.readAll();
    file.close();

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(value.toUtf8(), &error);

    if (!(error.error == QJsonParseError::NoError)) {
        qDebug() << "No tasks.json" << endl;
        return;
    }

    QJsonArray task_array = doc.array();

    for(int i=0; i < task_array.size(); i++) {
        if(task_array[i].isObject()) {
            QJsonObject obj = task_array[i].toObject();

            TASK_STATE state;
            if(obj["state"].toString() == "active") {
                state = ACTIVE;
            }
            else {
                state = COMPLETED;
            }

            Task new_task(obj["tid"].toString(), obj["tname"].toString(), obj["owner"].toString(), QDateTime::fromString(obj["begin_time"].toString(), datetime_format),
                    QDateTime::fromString(obj["end_time"].toString(), datetime_format), obj["save_path"].toString(), state);

            if(obj["hand_in_states"].isObject()) {
                QJsonObject hand_in_states = obj["hand_in_states"].toObject();
                QStringList list = hand_in_states.keys();
                for(int i=0; i < list.size(); i++) {
                    new_task.add_member(list[i], hand_in_states[list[i]].toString());
                }
            }

            tasks.push_back(new_task);
        }
    }
}

User& get_user_by_name(const QString &name, QVector<User> &users)
{
    for(int i=0; i < users.size(); i++) {
        if(name == users[i].getId()) {
            return users[i];
        }
    }
    return err_user;
}

Group& get_group_by_name(const QString &name, QVector<Group> &groups)
{
    for(int i=0; i < groups.size(); i++) {
        if(name == groups[i].getGroup_name()) {
            return groups[i];
        }
    }
    return err_group;
}

Task& get_task_by_name(const QString &name, QVector<Task> &tasks)
{
    for(int i=0; i < tasks.size(); i++) {
        if(name == tasks[i].getTask_name()) {
            return tasks[i];
        }
    }
    return err_task;
}

bool is_exist(const QString &value, QVector<User> &users)
{
    for(int i=0; i < users.size(); i++) {
        if(value == users[i].getId()) {
            return true;
        }
    }
    return false;
}

bool is_exist(const QString &value, QVector<Group> &groups)
{
    for(int i=0; i < groups.size(); i++) {
        if(value == groups[i].getGroup_id()) {
            return true;
        }
    }
    return false;
}

bool is_exist(const QString &value, QVector<Task> &tasks)
{
    for(int i=0; i < tasks.size(); i++) {
        if(value == tasks[i].getTask_name()) {
            return true;
        }
    }
    return false;
}

void write_json_back()
{
    write_users();
    write_groups();
    write_tasks();
}

void write_users()
{
    QFile file(out_path + QDir::separator() + "users.json");

    QJsonArray array;
    for(User user : users) {
        array.append(user.to_json());
    }

    QJsonDocument doc(array);
    QByteArray data = doc.toJson();

    file.open(QIODevice::WriteOnly);
    file.write(data);
    file.close();
}

void write_groups()
{
    QFile file(out_path + QDir::separator() + "groups.json");

    QJsonArray array;
    for(Group group : groups) {
        array.append(group.to_json());
    }

    QJsonDocument doc(array);
    QByteArray data = doc.toJson();

    file.open(QIODevice::WriteOnly);
    file.write(data);
    file.close();
}

void write_tasks()
{
    QFile file(out_path + QDir::separator() + "tasks.json");

    QJsonArray array;
    for(Task task : tasks) {
        array.append(task.to_json());
    }

    QJsonDocument doc(array);
    QByteArray data = doc.toJson();

    file.open(QIODevice::WriteOnly);
    file.write(data);
    file.close();
}
